package genedit.gui.propertyDialogs;

import genedit.gui.GMainFrame;
import genedit.gui.exceptions.ElementNePostoji;
import genedit.gui.exceptions.ElementPostoji;
import genedit.gui.propertyDialogs.AbstractDialog.StanjeDijaloga;
import genedit.model.graph.ConnectionPoint;
import genedit.model.graph.GraphElement;
import genedit.model.graph.Link;
import genedit.model.graph.Property;
import genedit.model.graph.classModel.ClassModel;
import genedit.model.graph.classModel.GAttribute;
import genedit.model.graph.classModel.GAttributes;
import genedit.model.graph.classModel.GMethod;
import genedit.model.graph.classModel.GMethods;
import genedit.model.graph.classModel.GeneralizationLink;
import genedit.model.graph.classModel.InterfaceModel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;

@SuppressWarnings("serial")
public class InterfaceModelDialog extends AbstractDialog{

	protected JTable tableAttributes;
	protected String[] tableColumnsAttributes;
	protected JTable tableMethods;
	protected String[] tableColumnsMethods;
	protected DialogTableModel tableModelAttributes;
	protected DialogTableModel tableModelMethods;
	protected InterfaceModel modelEl; 
	
	public InterfaceModelDialog(JFrame parent, GraphElement element) {
		super(parent);
		this.element = element;
		setTitle(element.getName());
		
		tableColumnsAttributes = new String[4];
		tableColumnsAttributes[0] = GMainFrame.getInstance().getResourceBundle().getString("lblVisibility");
		tableColumnsAttributes[1] = GMainFrame.getInstance().getResourceBundle().getString("lblType");
		tableColumnsAttributes[2] = GMainFrame.getInstance().getResourceBundle().getString("lblName");
		tableColumnsAttributes[3] = GMainFrame.getInstance().getResourceBundle().getString("lblPredef");
	
		for (Property p : ((InterfaceModel)element).getProperties()) {
			if(p.getKey().equals("attributes"))
			tableModelAttributes = new DialogTableModel(tableColumnsAttributes, (GAttributes)p.getValue());
		}
		
		tableColumnsMethods = new String[4];
		tableColumnsMethods[0] = GMainFrame.getInstance().getResourceBundle().getString("lblVisibility");
		tableColumnsMethods[1] = GMainFrame.getInstance().getResourceBundle().getString("lblRetType");
		tableColumnsMethods[2] = GMainFrame.getInstance().getResourceBundle().getString("lblName");
		tableColumnsMethods[3] = GMainFrame.getInstance().getResourceBundle().getString("lblParameter");
	
		for (Property p : ((InterfaceModel)element).getProperties()) {
			if(p.getKey().equals("methods"))
				tableModelMethods = new DialogTableModel(tableColumnsMethods, (GMethods)p.getValue());
		}
		
		
		initGUI();
		
		
		JPanel panTableAttributes = new JPanel(new BorderLayout());
		panTableAttributes.setBackground(Color.WHITE);
		tableAttributes = new JTable(tableModelAttributes);
		tableAttributes.setAutoCreateRowSorter(true);
		tableAttributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		tableAttributes.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		
		panTableAttributes.add(new JScrollPane(tableAttributes), BorderLayout.CENTER);
		
		
		JPanel panTableMethods = new JPanel(new BorderLayout());
		panTableMethods.setBackground(Color.WHITE);
		tableMethods = new JTable(tableModelMethods);
		tableMethods.setAutoCreateRowSorter(true);
		tableMethods.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		tableMethods.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		
		panTableMethods.add(new JScrollPane(tableMethods), BorderLayout.CENTER);
		
		JPanel panSouth = new JPanel();
		panSouth.setLayout(new BoxLayout(panSouth, BoxLayout.PAGE_AXIS));
		 modelEl = (InterfaceModel)this.element;
		 btnOkDialog = new JButton(GMainFrame.getInstance().getResourceBundle().getString("btnOk"));
		 btnOkDialog.addActionListener(new ActionListener() {
			 private void goDepth(GraphElement model) {
			 		performPropagation(model);
					ArrayList<GraphElement> row = new ArrayList<GraphElement>();
					 for(ConnectionPoint cp : model.getConnectionPoints()){
							for(Link link : cp.getEnding())
								if(link instanceof GeneralizationLink)
								row.add(link.getStart().getParent());
					 }
					 if(row.size()!=0)
						 for(GraphElement element : row)
							 goDepth(element);
					 else return;
		 }
		 
			 private void performPropagation(GraphElement model) {
			 for(ConnectionPoint cp : model.getConnectionPoints()){
					for(Link link : cp.getEnding()){
						if(link instanceof GeneralizationLink) {
							for (Property p : model.getProperties()) {
								if(p.getKey().equals("methods")){
									for (Property p1 : link.getStart().getParent().getProperties())
										if(p1.getKey().equals("methods")){
											for(GMethod method : ((GMethods)p.getValue()).getMethods()){
												if(!((GMethods)p1.getValue()).getMethods().contains(method)&& link.getEnd().getParent() instanceof ClassModel &&
														!((GMethods)p1.getValue()).getInheritedMethods().contains(method))
													((GMethods)p1.getValue()).getInheritedMethods().add(method);
												else if(!((GMethods)p1.getValue()).getMethods().contains(method)&& link.getEnd().getParent() instanceof InterfaceModel &&
														!((GMethods)p1.getValue()).getInheritedMethods().contains(method))
													((GMethods)p1.getValue()).getMethods().add(method);
										
											}
											for(GMethod method : ((GMethods)p.getValue()).getInheritedMethods()){
												if(!((GMethods)p1.getValue()).getMethods().contains(method)&& model instanceof ClassModel &&
														!((GMethods)p1.getValue()).getInheritedMethods().contains(method))
													((GMethods)p1.getValue()).getInheritedMethods().add(method);
												else if(!((GMethods)p1.getValue()).getMethods().contains(method)&& model instanceof InterfaceModel &&
														!((GMethods)p1.getValue()).getInheritedMethods().contains(method))
													((GMethods)p1.getValue()).getMethods().add(method);
										
											}
										}
									}
								else {
									for (Property p1 : link.getStart().getParent().getProperties())
										if(p1.getKey().equals("attributes")){
											for(String attribute : ((GAttributes)p.getValue()).getAtributeKeys())
												if(!((GAttributes)p1.getValue()).getAttributes().containsKey(attribute) && !((GAttributes)p1.getValue()).getInheritedAttributes().containsKey(attribute))
													try {													
														((GAttributes)p1.getValue()).getInheritedAttributes().put(attribute, ((GAttributes)p.getValue()).getAtribute(attribute));
													} catch (ElementNePostoji e) {
													// TODO Auto-generated catch block
													e.printStackTrace();
												}	
											for(String attribute : ((GAttributes)p.getValue()).getInheritedAttributes().keySet())
												if(!((GAttributes)p1.getValue()).getAttributes().containsKey(attribute) && !((GAttributes)p1.getValue()).getInheritedAttributes().containsKey(attribute))
													((GAttributes)p1.getValue()).getInheritedAttributes().put(attribute, ((GAttributes)p.getValue()).getInheritedAttributes().get(attribute));
										}
								}
							}
					}
				}
				}
		 }
			@Override
			public void actionPerformed(ActionEvent arg0) {
						modelEl.setName(txtNameDialog.getText());
						goDepth(modelEl);
						setVisible(false);
			}
		});
		 btnOkDialog.setAlignmentX( 
				Component.CENTER_ALIGNMENT); 
		panSouth.add(Box.createVerticalGlue()); 
		panSouth.add(btnOkDialog); 
		panSouth.add(Box.createVerticalGlue());;
		add(panSouth, BorderLayout.SOUTH);
		btnOkDialog.setText(GMainFrame.getInstance().getResourceBundle().getString("btnOk"));

		this.jtabbed.addTab(GMainFrame.getInstance().getResourceBundle().getString("Atributi"), panTableAttributes);
		this.jtabbed.addTab(GMainFrame.getInstance().getResourceBundle().getString("Metode"), panTableMethods);
		super.add(this.jtabbed, BorderLayout.CENTER);
		
		tableAttributes.getColumnModel().getColumn(0).setMinWidth(100);
		tableAttributes.getColumnModel().getColumn(1).setMinWidth(100);
		tableAttributes.getColumnModel().getColumn(2).setMinWidth(100);
		tableAttributes.getColumnModel().getColumn(3).setMinWidth(100);
		
		tableMethods.getColumnModel().getColumn(0).setMinWidth(100);
		tableMethods.getColumnModel().getColumn(1).setMinWidth(100);
		tableMethods.getColumnModel().getColumn(2).setMinWidth(100);
		tableMethods.getColumnModel().getColumn(3).setMinWidth(100);
		
		
	}


	@Override
	public void dodavanje() {
		// TODO Auto-generated method stub
		if(this.jtabbed.getSelectedIndex()==0){
			GAttribute novi = new GAttribute();
			PanelDetailAttribute panelDetailDodavanje = new PanelDetailAttribute(StanjeDijaloga.ADD, this, novi);
		AddUpdateDialog addUpdateDialog = new AddUpdateDialog(this, 
				GMainFrame.getInstance().getResourceBundle().getString("DodavanjeAtributa"), StanjeDijaloga.ADD, panelDetailDodavanje);
		addUpdateDialog.setVisible(true);
		
		if (addUpdateDialog.getClosingMode() == AddUpdateDialog.OK) {
			
			novi.setType(panelDetailDodavanje.getTxtType().getText()); 
			novi.setName(panelDetailDodavanje.getTxtName().getText());
			novi.setVisibilityType((String)panelDetailDodavanje.getCmbVisibility().getSelectedItem());
			novi.setPreDef(panelDetailDodavanje.getTxtPredef().getText()); 
			try {
				GAttributes ga = null;
				for (Property p : ((InterfaceModel)element).getProperties()) {
					if(p.getKey().equals("attributes")){
						((GAttributes)p.getValue()).addAtribute(novi);
					ga = (GAttributes)p.getValue();
					}
				}
				tableModelAttributes.fireTableDataChanged();
				int i = 0;
				for (String key : ga.getAtributeKeys()) {
					{
						if (key.equals(novi.getName()))
						break;
						else i++;
					}
				}
				tableAttributes.changeSelection(i, 0, false, false);
			}catch (ElementPostoji e) {
				JOptionPane.showMessageDialog(InterfaceModelDialog.this, e.getMessage());
			}
			}
		}	else {
			GMethod novi = new GMethod();
			PanelDetailMethod panelDetailDodavanje = new PanelDetailMethod(StanjeDijaloga.ADD, this, element, novi);
			AddUpdateDialog addUpdateDialog = new AddUpdateDialog(this, 
					GMainFrame.getInstance().getResourceBundle().getString("DodavanjeMetode"), StanjeDijaloga.ADD, panelDetailDodavanje);
			addUpdateDialog.setVisible(true);
			
			if (addUpdateDialog.getClosingMode() == AddUpdateDialog.OK) {
				
				novi.setReturnType(panelDetailDodavanje.getTxtType().getText()); 
				novi.setName(panelDetailDodavanje.getTxtName().getText());
				novi.setVisibilityType("public");	
				try {
					GMethods ga = null;
					for (Property p : ((InterfaceModel)element).getProperties()) {
						if(p.getKey().equals("methods")){
							((GMethods)p.getValue()).addMethod(novi);
						ga = (GMethods)p.getValue();
						}
					}
					tableModelMethods.fireTableDataChanged();
					int i = 0;
					for (GMethod key : ga.getMethods()) {
						{
							if (key.equals(novi.getName()) && key.equals(novi.getReturnType()))
							break;
							else i++;
						}
					}
					tableMethods.changeSelection(i, 0, false, false);
				}catch (ElementPostoji e) {
					JOptionPane.showMessageDialog(InterfaceModelDialog.this, e.getMessage());
				}
				}
		}

	}

	@Override
	public void izmena() {
		// TODO Auto-generated method stub
		if(this.jtabbed.getSelectedIndex()==0){
		if(tableAttributes.getSelectedRow() != -1 )
		{
			PanelDetailAttribute panelDetailIzmena = null;
			int row = tableAttributes.getSelectedRow();
			String name = (String) tableAttributes.getValueAt(row, 2);
			try {
				for (Property p : ((InterfaceModel)element).getProperties()) {
					if(p.getKey().equals("attributes")){
				panelDetailIzmena = new PanelDetailAttribute(StanjeDijaloga.UPDATE, this, ((GAttributes)p.getValue()).getAtribute(name));
				panelDetailIzmena.getTxtName().setText(((GAttributes)p.getValue()).getAtribute(name).getName());
				panelDetailIzmena.getTxtType().setText(((GAttributes)p.getValue()).getAtribute(name).getType());
				panelDetailIzmena.getTxtPredef().setText(((GAttributes)p.getValue()).getAtribute(name).getPreDef());
					}
				}
			
			} catch (ElementNePostoji e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			AddUpdateDialog addUpdateDialog = new AddUpdateDialog(this, 
				GMainFrame.getInstance().getResourceBundle().getString("IzmenaAtributa"), StanjeDijaloga.UPDATE, panelDetailIzmena);
		addUpdateDialog.setVisible(true);
		
		if (addUpdateDialog.getClosingMode() == addUpdateDialog.OK) {
			try {
			for (Property p : ((InterfaceModel)element).getProperties()) {
				if(p.getKey().equals("attributes")){
					((GAttributes)p.getValue()).getAtribute(name).setType(panelDetailIzmena.getTxtType().getText());
					((GAttributes)p.getValue()).getAtribute(name).setPreDef(panelDetailIzmena.getTxtPredef().getText());
					((GAttributes)p.getValue()).getAtribute(name).setName(panelDetailIzmena.getTxtName().getText());
				}
			
			}
			tableModelAttributes.fireTableDataChanged();
			tableAttributes.changeSelection(row, 0, false, false);
			} catch (ElementNePostoji e) {
				JOptionPane.showMessageDialog(InterfaceModelDialog.this, e.getMessage());
			}
		
			
		}

		}
		} else {
			if(tableMethods.getSelectedRow() != -1 )
			{
				PanelDetailMethod panelDetailIzmena = null;
				int row = tableMethods.getSelectedRow();
				String name = (String) tableMethods.getValueAt(row, 2);
				try {
					for (Property p : ((InterfaceModel)element).getProperties()) {
						if(p.getKey().equals("methods")){
					panelDetailIzmena = new PanelDetailMethod(StanjeDijaloga.UPDATE, this, element, ((GMethods)p.getValue()).getMethod(name));
					panelDetailIzmena.getTxtType().setText(((GMethods)p.getValue()).getMethod(name).getReturnType());
					panelDetailIzmena.getTxtName().setText(((GMethods)p.getValue()).getMethod(name).getName());
					}
					}
				
				} catch (ElementNePostoji e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				AddUpdateDialog addUpdateDialog = new AddUpdateDialog(this, 
					GMainFrame.getInstance().getResourceBundle().getString("IzmenaMetode"), StanjeDijaloga.UPDATE, panelDetailIzmena);
			addUpdateDialog.setVisible(true);
			
			if (addUpdateDialog.getClosingMode() == addUpdateDialog.OK) {

				for (Property p : ((InterfaceModel)element).getProperties()) {
					if(p.getKey().equals("methods")){
						((GMethods)p.getValue()).getMethodbyName(name).setReturnType(panelDetailIzmena.getTxtType().getText());
						((GMethods)p.getValue()).getMethodbyName(name).setName(panelDetailIzmena.getTxtName().getText());						
					}
				
				}
				tableModelMethods.fireTableDataChanged();
				tableMethods.changeSelection(row, 0, false, false);
			
				
			}
			}
		}
	}

	@Override
	public void brisanje() {
		// TODO Auto-generated method stub
		if(this.jtabbed.getSelectedIndex()==0){
		if(tableAttributes.getSelectedRow() != -1 )
		{
			
			int row = tableAttributes.getSelectedRow();
			String name = (String) tableAttributes.getValueAt(row, 2);
			GAttribute attribute = null;
			try {
				for (Property p : ((InterfaceModel)element).getProperties()) {
					if(p.getKey().equals("attributes")){						
				attribute = ((GAttributes)p.getValue()).getAtribute(name);
				((GAttributes)p.getValue()).removeAtribute(attribute);
				tableModelAttributes.fireTableDataChanged();
					}
				}
			} catch (ElementNePostoji e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
							
						
		}
			
	} else {
		if(tableMethods.getSelectedRow() != -1 )
		{
			
			int row = tableMethods.getSelectedRow();
			String name = (String) tableMethods.getValueAt(row, 2);
			GMethod method = null;
			try {
				for (Property p : ((InterfaceModel)element).getProperties()) {
					if(p.getKey().equals("methods")){						
						method = ((GMethods)p.getValue()).getMethod(name);
						((GMethods)p.getValue()).removeMethod(method);
						tableModelMethods.fireTableDataChanged();
					}
				}
			} catch (ElementNePostoji e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
	}

	}
	}

}

